package handlers

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"go.uber.org/zap"
	"gogogo-server/gameserver/global"
	"gogogo-server/gameserver/protocols"
	"gogogo-server/share/http_helper"
	"net/http"
	"time"
)

type MessageHandler interface {
	HandleMessage(*websocket.Conn, *protocols.Message) error
}

// RoleBasicInfo 角色基础信息
type RoleBasicInfo struct {
	Account     string
	RoleUid     uint64
	SendMsgChan chan string
	RoleStatus  int // 目前预想的是维护登录进度状态
}

// ClientContext 接收客户端消息的context
type ClientContext struct {
	RoleUid uint64
	msg     *protocols.Message
}

type HttpResponseData struct {
	status int
	body   []byte
}

type AsyncHttpContext struct {
	url          string
	param        string
	callbackChan chan HttpResponseData
	timeout      time.Duration // 超时时间
}

// Callback 异步http的ch返回
func (ctx *AsyncHttpContext) Callback(status int, msg []byte) {
	ctx.callbackChan <- HttpResponseData{
		status: status,
		body:   msg,
	}
}

// MessageHandlerManager 总的消息管理器
type MessageHandlerManager struct {
	messageHandlers      map[string]MessageHandler
	receiveClientMsgChan chan *ClientContext
	loadClientMsgChan    chan string // 专门用于角色登录加载的
	asyncHttpChan        chan *AsyncHttpContext
	RoleMap              map[uint64]*RoleBasicInfo
}

var msgHandlerMgr *MessageHandlerManager

func (mgr *MessageHandlerManager) receiveMsgCoroutine() {
	for {
		select {
		case ctx := <-mgr.receiveClientMsgChan:
			zap.S().Infof("收到角色:%d 的消息:%s", ctx.RoleUid, ctx.msg)
			_, ok := mgr.RoleMap[ctx.RoleUid]
			if !ok {
				zap.S().Warnf("角色:%d 未登录加载数据但收到了消息:%s,断开连接", ctx.RoleUid, ctx.msg.Event)
				continue
			}
		case account := <-mgr.loadClientMsgChan:
			zap.S().Infof("准备加载角色:%s", account)
		}
	}
}

func (mgr *MessageHandlerManager) asyncHttpCoroutine() {
	c := http.Client{}
	for ctx := range mgr.asyncHttpChan {
		c.Timeout = ctx.timeout
		err, status, resp := http_helper.ClientInstance().Post(ctx.url, "application/json", ctx.param, ctx.timeout)
		if err != nil {
			zap.S().Infof("http请求失败:%s, status:%d", err, status)
		}
		ctx.Callback(status, resp)
	}
}

func OnReceiveClientMsg(roleUid uint64, msg *protocols.Message) {
	msgHandlerMgr.receiveClientMsgChan <- &ClientContext{
		RoleUid: roleUid,
		msg:     msg,
	}
}

type ServerVerifyResult struct {
	Account string
}

// TryVerifyLogin 登录验证角色
func TryVerifyLogin(token string, info *RoleBasicInfo) bool {
	if len(token) == 0 {
		return false
	}
	ch := make(chan HttpResponseData)
	msgHandlerMgr.asyncHttpChan <- &AsyncHttpContext{
		url:          global.GGG_CONFIG.LoginAddr + "/server/verify",
		param:        fmt.Sprintf("token=%s", token),
		timeout:      5 * time.Second,
		callbackChan: ch,
	}
	resp := <-ch
	if resp.status != http.StatusOK {
		return false
	}
	var result ServerVerifyResult
	if err := json.Unmarshal(resp.body, &result); err != nil || len(result.Account) == 0 {
		return false
	}
	info.Account = result.Account
	zap.S().Infof("根据token:%s 加载到账号:%s", token, result.Account)
	msgHandlerMgr.loadClientMsgChan <- info.Account
	return true
}

func InitMessageHandlers() {
	msgHandlerMgr = &MessageHandlerManager{
		receiveClientMsgChan: make(chan *ClientContext),
		loadClientMsgChan:    make(chan string),
		asyncHttpChan:        make(chan *AsyncHttpContext),
	}
	var gameRoomHandler = NewRoomHandler()
	var loginHandler = NewLoginHandler()
	msgHandlerMgr.messageHandlers = map[string]MessageHandler{
		"room.create": gameRoomHandler,
		"room.join":   gameRoomHandler,
		"login":       loginHandler,
		// 更多消息类型和处理器
	}
	go msgHandlerMgr.receiveMsgCoroutine()
	go msgHandlerMgr.asyncHttpCoroutine()
}

func DestroyMessageHandlers() {
	if nil != msgHandlerMgr {
		close(msgHandlerMgr.receiveClientMsgChan)
		close(msgHandlerMgr.loadClientMsgChan)
		close(msgHandlerMgr.asyncHttpChan)
	}
}
